# TS: OHLCV xts Object
# OrderTS: Same index as TS, column "long", "short", "stoploss", "stopwin"
orderLogic <- function(TS, OrderTS, n=10, entry="c0", wholeSeries=FALSE) {
  checkPeriod <- function(period) {                          # OrderTS is global in this context
    lastrun <- !(n > period)
    stopped <- OrderTS[,"S_L"] | OrderTS[,"S_W"]
    OrderTS[,"S_L"] <<- OrderTS[,"S_L"] | (!OrderTS[,"S_W"] &
      (OrderTS[,"stoploss"] & Lo(LAGTS) < OrderTS[,"stoploss"] & OrderTS[,"long"] | # loss-stopped out long position
      OrderTS[,"stoploss"] & Hi(LAGTS) > OrderTS[,"stoploss"] & OrderTS[,"short"])) # loss-stopped out short position
    OrderTS[,"S_W"] <<- OrderTS[,"S_W"] | (!OrderTS[,"S_L"] &
      (OrderTS[,"stopwin"] & Hi(LAGTS) > OrderTS[,"stopwin"] & OrderTS[,"long"] |   # win-stopped out long position
      OrderTS[,"stopwin"] & Lo(LAGTS) < OrderTS[,"stopwin"] & OrderTS[,"short"]))   # win-stopped out short position
    juststopped <- !stopped & (OrderTS[,"S_L"] | OrderTS[,"S_W"])
    OrderTS[,"period"] <<- OrderTS[,"period"] +              # set period when stop-out occurred
      period * juststopped +
      (!OrderTS[,"period"] & !juststopped & lastrun) * period               # or when last run
    OrderTS[,"days"] <<- OrderTS[,"days"] +                  # set the number of actual days
      juststopped * (LAGTS[,"indexday"] - TS[,"indexday"]) +
      (!OrderTS[,"days"] & !juststopped & lastrun) * (LAGTS[,"indexday"] - TS[,"indexday"])
    SLOP <- merge.xts(OrderTS[,"stoploss"],Op(LAGTS))
    SWOP <- merge.xts(OrderTS[,"stopwin"],Op(LAGTS))
    OrderTS[,"closeprice"] <<- OrderTS[,"closeprice"] +      # set close-out price
      # handle stoploss for long position
      as.xts (apply(SLOP,1,min)) *
      (OrderTS[,"S_L"] & juststopped & OrderTS[,"long"]) +
      # handle stoploss for short position
      as.xts (apply(SLOP,1,max)) *
      (OrderTS[,"S_L"] & juststopped & OrderTS[,"short"]) +
      # handle stopwin for long position
      as.xts (apply(SWOP,1,max)) * 
      (OrderTS[,"S_W"] & juststopped & OrderTS[,"long"]) +
      # handle stopwin for short position
      as.xts (apply(SWOP,1,min)) *
      (OrderTS[,"S_W"] & juststopped & OrderTS[,"short"])
  }
  # append the column indexday to TS
  namesTS <- colnames(TS)
  TS <- cbind(TS, .indexday(TS))
  colnames(TS) <- c(namesTS, "indexday")
  
  namesOrderTS <- colnames(OrderTS)
  OrderTS <- merge(OrderTS, 0, 0, 0, 0, 0, 0, 0)                   # append columns to OrderTS
  colnames(OrderTS) <- c(namesOrderTS, "S_L", "S_W", "period", "days", "openprice", "closeprice", "return")

  # set openprice at close price when long/short signal is there
  if (entry=="c0") {
    OrderTS[,"openprice"] <- (OrderTS[,"long"] | OrderTS[,"short"]) * Cl(TS)    
  } else if (entry=="o1") {
    OrderTS[,"openprice"] <- (OrderTS[,"long"] | OrderTS[,"short"]) * as.xts(Next(Op(TS)))
  } else if (entry=="c1") {
    OrderTS[,"openprice"] <- (OrderTS[,"long"] | OrderTS[,"short"]) * as.xts(Next(Cl(TS)))   
  }

  for (i in 1:n) {
    LAGTS <- LagOHLCindexday(TS, k=(i*-1))
    checkPeriod(i)
  }
  # fill closeprice after n periods for not-stopped-out positions
  OrderTS[,"closeprice"] <- OrderTS[,"closeprice"] +
    Cl(LAGTS) *!(OrderTS[,"S_L"] | OrderTS[,"S_W"])
  # calculate return for long positions
  OrderTS[,"return"] <- 
    OrderTS[,"long"] * (OrderTS[,"closeprice"] / OrderTS[,"openprice"] -1) + 
    OrderTS[,"short"]* (1- (OrderTS[,"closeprice"]/ OrderTS[,"openprice"]))
  if (wholeSeries == TRUE) {
    return(OrderTS)
  } else {
    trade=OrderTS[,"long"] | OrderTS[,"short"]
    return(OrderTS[trade])
  }
}

